package com.zc.serviceuser.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zc.commonutils.Constants;
import com.zc.commonutils.Result;
import com.zc.exceptionhandler.ZcException;
import com.zc.feign.clients.LogClient;
import com.zc.feign.entity.Log;
import com.zc.serviceuser.entity.User;
import com.zc.serviceuser.entity.dto.LoginFormDTO;
import com.zc.serviceuser.entity.dto.LoginFormDTOTwo;
import com.zc.serviceuser.entity.dto.UserDTO;
import com.zc.serviceuser.entity.dto.registerFormDTO;
import com.zc.serviceuser.listener.ExcelListener;
import com.zc.serviceuser.mapper.UserMapper;
import com.zc.serviceuser.service.IUserService;
import com.zc.serviceuser.user.ExcelUser;
import com.zc.serviceuser.user.ReadUser;
import com.zc.serviceuser.utils.RandomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ObjectMapper objectMapper;

    @Autowired
    private LogClient logClient;

    @Override
    public Result login(LoginFormDTO loginForm) throws JsonProcessingException {
        String phone = loginForm.getPhone();
        //String password = loginForm.getPassword();
        // 从redis获取验证码并校验
        String cacheCode = stringRedisTemplate.opsForValue().get(Constants.LOGIN_CODE_KEY + phone);
        String code = loginForm.getCode();
        if (cacheCode == null || !cacheCode.equals(code)) {
            // 不一致，报错
            return Result.error().message("验证码错误");
        }

        // 4.一致，根据手机号查询用户 select * from tb_user where phone = ?
        User user = query().eq("phone", phone).one();

        // 5.判断用户是否存在
        if (user == null) {
            // 6.不存在，创建新用户并保存
//            com.zc.user = createUserWithPhone(phone);
            return Result.error().message("账号不存在,请先注册");
        }

        // 7.保存用户信息到 redis中
        // 7.1.随机生成token，作为登录令牌
        String token = UUID.randomUUID().toString();
        // 7.2.将User对象转为HashMap存储
//        UserDTO userDTO = new UserDTO();
//        userDTO.setId(user.getId());
//        userDTO.setUsername(user.getUserName());
//        userDTO.setRole(user.getRole());

        String userDTOStr = objectMapper.writeValueAsString(user);

        // 7.3.存储
        String tokenKey = Constants.LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForValue().set(tokenKey,userDTOStr);
        // 7.4.设置token有效期
        stringRedisTemplate.expire(tokenKey, Constants.LOGIN_USER_TTL, TimeUnit.MINUTES);
        stringRedisTemplate.delete(Constants.LOGIN_CODE_KEY + phone);
        // 8.返回token
        return Result.ok().data("token",token).data("role",user.getRole()).data("id",user.getId());
    }

    @Override
    public Result register(registerFormDTO registerFormDTO) {
        String phone = registerFormDTO.getPhone();
        String cacheCode = stringRedisTemplate.opsForValue().get(Constants.LOGIN_CODE_KEY + phone);
        String code = registerFormDTO.getCode();
        if (cacheCode == null || !cacheCode.equals(code)) {
            // 不一致，报错
            return Result.error().message("验证码错误");
        }

        User user = query().eq("phone", phone).one();
        if (user==null){
            //创建用户
             user = new User();
            user.setPhone(registerFormDTO.getPhone());
            user.setPassword(registerFormDTO.getPassword());
            if (StringUtils.isBlank(registerFormDTO.getUserName())){
                user.setUserName(Constants.USER_NICK_NAME_PREFIX+ RandomUtil.getSixBitRandom());
            }
            user.setUserName(registerFormDTO.getUserName());
            save(user);
            stringRedisTemplate.delete(Constants.LOGIN_CODE_KEY + phone);
            return Result.ok().message("注册成功");
        }else {
            return Result.error().message("该用户已存在");
        }


    }

    @Override
    public Result loginTwo(LoginFormDTOTwo loginFormDTOTwo) throws JsonProcessingException {

        String phone = loginFormDTOTwo.getPhone();
        String password = loginFormDTOTwo.getPassword();


        // 4.一致，根据手机号查询用户 select * from tb_user where phone = ?
        User user = query().eq("phone", phone).eq("password",password).one();

        // 5.判断用户是否存在
        if (user == null) {
            // 6.不存在，创建新用户并保存
//            com.zc.user = createUserWithPhone(phone);
            return Result.error().message("账号不存在或密码错误");
        }

        // 7.保存用户信息到 redis中
        // 7.1.随机生成token，作为登录令牌
        String token = UUID.randomUUID().toString();
        // 7.2.将User对象转为HashMap存储
//        UserDTO userDTO = new UserDTO();
//        userDTO.setId(user.getId());
//        userDTO.setUsername(user.getUserName());
//        userDTO.setRole(user.getRole());

        String userDTOStr = objectMapper.writeValueAsString(user);

        // 7.3.存储
        String tokenKey = Constants.LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForValue().set(tokenKey,userDTOStr);
        // 7.4.设置token有效期
        stringRedisTemplate.expire(tokenKey, Constants.LOGIN_USER_TTL, TimeUnit.MINUTES);
        stringRedisTemplate.delete(Constants.LOGIN_CODE_KEY + phone);

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",loginFormDTOTwo.getPhone());
        User one = getOne(wrapper);
        Log log = new Log();
        log.setUid(one.getId());
        log.setContent("用户"+loginFormDTOTwo.getPhone()+"登录了");
        log.setGrade("正常");
        logClient.addLog(log);
        // 8.返回token

        return Result.ok().data("token",token).data("role",user.getRole()).data("id",user.getId());

    }


    @Override
    public Result readExcel(MultipartFile file, UserServiceImpl userService) {

        if (file==null){
            return Result.error().message("文件为空");
        }
        try {
            InputStream inputStream = file.getInputStream();
             EasyExcel.read(inputStream, ReadUser.class, new ExcelListener(userService)).sheet().doRead();
            return Result.ok();
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error();
        }
    }

    @Override
    public void wireExcel(String description, HttpServletResponse response) {

        //导出数据
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(org.apache.commons.lang.StringUtils.isNotBlank(description), "description", description);
        List<User> list = list(queryWrapper);

        LocalDateTime now = LocalDateTime.now();
        String time = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒").format(now);

        // 设置响应头
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = "data.xlsx";
        String encodedFileName = null;
        ExcelWriter excelWriter = null;
        try {
            encodedFileName = URLEncoder.encode(fileName, "UTF-8");

            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
            // 创建ExcelWriter对象
            excelWriter = EasyExcel.write(response.getOutputStream(), ExcelUser.class).build();
            // 创建写入的Sheet
            WriteSheet writeSheet = EasyExcel.writerSheet("用户信息").build();

            // 执行导出操作，写入数据到Excel
            excelWriter.write(list, writeSheet);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭ExcelWriter对象
            assert excelWriter != null;
            excelWriter.finish();
        }

    }
}



